import os
import re

def batch_rename():
    # 获取文件夹路径
    folder = input("请输入要重命名的文件夹绝对路径：").strip()
    
    # 检查路径是否存在
    if not os.path.exists(folder):
        print("错误：路径不存在！")
        return
    
    # 获取文件列表（排除子文件夹）
    files = [f for f in os.listdir(folder) if os.path.isfile(os.path.join(folder, f))]
    if not files:
        print("该文件夹中没有可重命名的文件")
        return

    # 显示重命名选项
    print("\n请选择重命名模式：")
    print("1. 添加前缀")
    print("2. 添加后缀")
    print("3. 替换文本")
    print("4. 序号重命名")
    print("5. 删除指定字符串")
    print("6. 根据上下文删除")
    print("7. 指定位置插入")
    print("8. 删除前缀")
    
    try:
        mode = int(input("请输入选项数字（1-8）："))
        if mode not in [1,2,3,4,5,6,7,8]:
            raise ValueError
    except:
        print("无效的选项！")
        return

    # 根据不同模式处理
    rename_plan = []
    
    if mode == 1:  # 添加前缀
        prefix = input("请输入要添加的前缀：").strip()
        for f in files:
            new_name = prefix + f
            rename_plan.append((f, new_name))
    
    elif mode == 2:  # 添加后缀
        suffix = input("请输入要添加的后缀（不包括扩展名）：").strip()
        for f in files:
            name, ext = os.path.splitext(f)
            new_name = f"{name}{suffix}{ext}"
            rename_plan.append((f, new_name))
    
    elif mode == 3:  # 替换文本
        old_str = input("请输入要替换的文本：").strip()
        new_str = input("请输入替换后的新文本：").strip()
        for f in files:
            new_name = f.replace(old_str, new_str)
            rename_plan.append((f, new_name))
    
    elif mode == 4:  # 序号重命名
        try:
            start = int(input("请输入起始序号（默认1）：") or 1)
            digits = int(input("请输入序号位数（默认3）：") or 3)
            template = input("请输入命名模板（可用{}代替序号，默认'{}_'）：") or "{}_"
        except:
            print("输入格式错误！")
            return
        
        # 生成格式化字符串
        fmt = "{:0" + str(digits) + "d}"
        for i, f in enumerate(sorted(files), start=start):
            serial = fmt.format(i)
            new_name = template.format(serial) + f
            rename_plan.append((f, new_name))

    elif mode == 5:  # 删除指定字符串（增强版）
        del_strs = input("请输入要删除的字符串（多个用逗号分隔）：").strip()
        if not del_strs:
            print("错误：输入不能为空！")
            return
        
        # 处理输入并去重
        str_list = list(set([s.strip() for s in del_strs.split(",") if s.strip()]))
        if not str_list:
            print("错误：没有有效的删除字符串！")
            return

        # 扩展名保护模式选择
        protect_ext = input("是否保护扩展名？(y/n, 默认y)：").lower() or 'y'
        
        for f in files:
            original_name = f
            # 分割文件名和扩展名
            name_part, ext_part = os.path.splitext(f)
            
            # 执行删除操作
            for s in str_list:
                if protect_ext == 'y':
                    # 只处理文件名部分
                    name_part = name_part.replace(s, "")
                else:
                    # 处理整个文件名（含扩展名）
                    original_name = original_name.replace(s, "")
            
            # 重新组合文件名
            new_name = (name_part + ext_part) if protect_ext == 'y' else original_name
            
            # 空文件名检查
            if not new_name.strip('.').strip():  # 允许纯扩展名但必须有文件名
                print(f"错误：删除操作将导致无效文件名：{f}")
                return
                
            rename_plan.append((f, new_name))

    elif mode == 6:  # 修复的上下文删除模式
        print("\n请选择上下文删除类型：")
        print("1. 删除两个指定字符串之间的内容（包含边界）")
        print("2. 删除两个指定字符串之间的内容（保留边界）")
        print("3. 删除指定字符串前/后的内容")
        type_choice = input("请输入类型编号（1-3）：")

        protect_ext = input("是否保护扩展名？(y/n, 默认y)：").lower() or 'y'
        
        # 提前获取所有必要参数
        if type_choice in ['1', '2']:
            start_str = input("请输入起始字符串：").strip()
            end_str = input("请输入结束字符串：").strip()
            if not start_str or not end_str:
                print("错误：起始/结束字符串不能为空！")
                return
            
            # 修复正则表达式构造
            if type_choice == '1':
                # 包含边界的匹配模式：(start_str)(任意内容)(end_str)
                pattern_str = f'({re.escape(start_str)})(.*?)({re.escape(end_str)})'
                replacement = ''
            else:
                # 保留边界的匹配模式：start_str(中间内容)end_str
                pattern_str = f'{re.escape(start_str)}(.*?){re.escape(end_str)}'
                replacement = r'\1\2'  # 保留边界字符串
                
            pattern = re.compile(pattern_str)
        elif type_choice == '3':
            direction = input("删除方向（前/后）：").strip().lower()
            target_str = input("请输入锚点字符串：").strip()
            if direction not in ['前', '后']:
                print("无效的方向输入！")
                return
        else:
            print("无效的类型选择！")
            return

        for f in files:
            name_part, ext_part = os.path.splitext(f)
            working_name = name_part if protect_ext == 'y' else f
            
            try:
                if type_choice in ['1', '2']:
                    # 使用subn获取替换次数
                    new_part, count = re.subn(pattern, replacement, working_name)
                    if count == 0:
                        print(f"警告：未找到匹配模式，保持原文件名：{f}")
                elif type_choice == '3':
                    if direction == '前':
                        new_part = working_name.split(target_str, 1)[-1] if target_str in working_name else working_name
                    else:
                        new_part = working_name.split(target_str, 1)[0] if target_str in working_name else working_name
                
                # 重组文件名
                new_name = (new_part + ext_part) if protect_ext == 'y' else new_part
                
                # 空文件名检查
                if not new_name.strip('.').strip():
                    print(f"错误：操作将导致无效文件名：{f}")
                    return
                    
                rename_plan.append((f, new_name))
            except Exception as e:
                print(f"处理文件 {f} 时出错：{str(e)}")
                return
                
    elif mode == 7:  # 修复的指定位置插入模式
        insert_str = input("请输入要插入的字符串：").strip()
        if not insert_str:
            print("错误：插入内容不能为空！")
            return

        print("\n请选择插入位置类型：")
        print("1. 按字符位置插入")
        print("2. 在指定字符串后插入")
        pos_type = input("请输入类型编号（1-2）：")

        protect_ext = input("是否保护扩展名？(y/n, 默认y)：").lower() or 'y'

        # 提前获取位置参数
        if pos_type == '1':
            try:
                position = int(input("请输入插入位置（从0开始计数）："))
            except:
                print("输入格式错误！")
                return
        elif pos_type == '2':
            anchor = input("请输入定位字符串：").strip()
        else:
            print("无效的位置类型！")
            return

        for f in files:
            name_part, ext_part = os.path.splitext(f)
            target = name_part if protect_ext == 'y' else f
            
            try:
                if pos_type == '1':
                    if position < 0 or position > len(target):
                        print(f"错误：无效的插入位置（0-{len(target)}）：{f}")
                        return
                    new_part = target[:position] + insert_str + target[position:]
                elif pos_type == '2':
                    split_index = target.find(anchor)
                    if split_index == -1:
                        new_part = target  # 未找到不插入
                    else:
                        insert_pos = split_index + len(anchor)
                        new_part = target[:insert_pos] + insert_str + target[insert_pos:]
                
                # 重组文件名
                new_name = (new_part + ext_part) if protect_ext == 'y' else new_part
                
                # 空文件名检查
                if not new_name.strip('.').strip():
                    print(f"错误：插入操作将导致无效文件名：{f}")
                    return
                    
                rename_plan.append((f, new_name))
            except Exception as e:
                print(f"处理文件 {f} 时出错：{str(e)}")
                return

    elif mode == 8:  # 新增删除前缀模式
        prefix = input("请输入要删除的前缀：").strip()
        if not prefix:
            print("错误：前缀不能为空！")
            return

        protect_ext = input("是否保护扩展名？(y/n, 默认y)：").lower() or 'y'
        strict_mode = input("是否严格匹配大小写？(y/n, 默认y)：").lower() or 'y'

        for f in files:
            # 分割文件名和扩展名
            name_part, ext_part = os.path.splitext(f)
            target = name_part if protect_ext == 'y' else f
            
            # 根据设置选择匹配方式
            if strict_mode == 'y':
                check_str = target
                remove_str = prefix
            else:
                check_str = target.lower()
                remove_str = prefix.lower()

            # 删除前缀逻辑
            if check_str.startswith(remove_str):
                new_part = target[len(prefix):]  # 保留删除前缀后的内容
            else:
                new_part = target  # 无匹配前缀保持原样

            # 重组文件名
            new_name = (new_part + ext_part) if protect_ext == 'y' else new_part

            # 空文件名检查
            if not new_name.strip('.').strip():
                print(f"错误：删除前缀将导致无效文件名：{f}")
                return
                
            rename_plan.append((f, new_name))
    
    # 检查是否有重名冲突
    conflicts = {}
    for old, new in rename_plan:
        if new in conflicts:
            conflicts[new].append(old)
        else:
            conflicts[new] = [old]
    
    # 处理冲突
    for new_name in list(conflicts.keys()):
        if len(conflicts[new_name]) > 1:
            print(f"检测到冲突：多个文件将重命名为 {new_name}")
            return
        if os.path.exists(os.path.join(folder, new_name)):
            print(f"警告：文件 {new_name} 已存在！")
            return

    # 显示预览
    print("\n预览修改：")
    for old, new in rename_plan:
        print(f"{old} -> {new}")
    
    # 用户确认
    confirm = input("\n是否执行重命名操作？(y/n)：").lower()
    if confirm != 'y':
        print("操作已取消")
        return

    # 执行重命名
    success = 0
    for old, new in rename_plan:
        try:
            os.rename(
                os.path.join(folder, old),
                os.path.join(folder, new)
            )
            success += 1
        except Exception as e:
            print(f"重命名 {old} 失败：{str(e)}")
    
    print(f"操作完成，成功重命名 {success}/{len(rename_plan)} 个文件")

if __name__ == "__main__":
    batch_rename()